<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
	<meta name="keywords" content="pilot mcp" />
	<meta name="description" content="pilot mcp" />
	<!-- 网页标签标题 -->
	<title>pilot mcp</title>
	<link rel="shortcut icon" href="https://img.alicdn.com/tfs/TB1hgJpHAPoK1RjSZKbXXX1IXXa-64-64.png"/>
	<link rel="stylesheet" href="/build/blogDetail.css" />
</head>
<body>
	<div id="root"><div class="blog-detail-page" data-reactroot=""><header class="header-container header-container-normal"><div class="header-body"><a href="/zh-cn/index.html"><img class="logo" src="/img/nacos_colorful.png"/></a><div class="search search-normal"><span class="icon-search"></span></div><span class="language-switch language-switch-normal">En</span><div class="header-menu"><img class="header-menu-toggle" src="/img/menu_gray.png"/><ul><li class="menu-item menu-item-normal"><a href="/zh-cn/index.html">首页</a></li><li class="menu-item menu-item-normal"><a href="/zh-cn/docs/what-is-nacos.html">文档</a></li><li class="menu-item menu-item-normal menu-item-normal-active"><a href="/zh-cn/blog/index.html">博客</a></li><li class="menu-item menu-item-normal"><a href="/zh-cn/community/index.html">社区</a></li><li class="menu-item menu-item-normal"><a href="https://cn.aliyun.com/product/aliware/mse?spm=nacos-website.topbar.0.0.0">企业版Nacos</a><img class="menu-img" src="https://img.alicdn.com/tfs/TB1esl_m.T1gK0jSZFrXXcNCXXa-200-200.png"/></li><li class="menu-item menu-item-normal"><a href="http://console.nacos.io/nacos/index.html">控制台样例</a></li></ul></div></div></header><section class="blog-content markdown-body"><h1>Pilot MCP协议介绍</h1>
<p><a name="VRC6c"></a></p>
<h1>背景介绍</h1>
<p>Istio是目前主流的Service Mesh组件。Istio基于Service Mesh的理念，承担着服务发现、服务通信、负载均衡、限流熔断、监控等等功能。让应用不用关心这些底层逻辑，专注于业务的开发和访问即可。软件行业的趋势一定是让业务的开发越来越轻松和简便，所以从这个角度看以Istio为代表的Service Mesh一定会越来越流行。至于目前存在的一些包括性能和设计复杂的问题，一定可以通过技术手段解决。</p>
<p><a name="hKDrO"></a></p>
<h1>总体架构</h1>
<p>MCP协议推出的背后，是Pilot意图重构以解决之前架构带来的代码维护、测试、扩展及稳定性等多方面的问题。在之前的架构中，Pilot内嵌了与K8S的交互逻辑以及其他扩展的注册中心和配置中心的逻辑。这样导致Pilot内部逻辑比较复杂、承担职责不够清晰。同时与各个组件的交互协议也不统一，导致Pilot难以维护这些代码，对于后面的扩展组件接入，也望而却步。在Pilot的重构设计文档中，对于Pilot目前存在的问题是这么总结的[1]：<br />“</p>
<ul>
<li>Pilot is more difficult to test than is necessary. It requires a dependency on K8S Apiserver in order to write more complex unit or simple integration tests.</li>
<li>We have smeared logic for dealing with the vagaries of K8S CRDs across Pilot, Mixer &amp; Citadel. Common concerns like K8S integration, resource validation and API versioning do not share a common implementation. The proposal to resurrect **Galley **is primarily motivated by an obvious need to improve our user-facing API experience.</li>
<li>Consuming the K8S API client in Pilot is a source of bloat and represents a production risk. Moving that risk to Galley while isolating the network control plane from it should be a performance and stability win.</li>
<li>The contract between Pilot, Kubernetes and other platforms is under-specified. We implicitly consume the totality of the K8S API surface even if we don’t need it.</li>
<li>Writing extensions to Pilot requires developers to consume our build process and this has proven to be a barrier to adoption for partners. This is analogous to the recent architectural shift in Mixer to use out-of-process adapters for the same reasons.</li>
</ul>
<p>”<br />
<br />Istio在Pilot重构设计文档中，展示了基于MCP协议的内部组件架构。在这个架构中，Pilot与Envoy还是使用Envoy定义的ADS协议，Pilot与Galley、外部的注册中心、配置中心以及其他的Pilot之间，都是通过MCP协议进行通讯：<br />
<br /><img src="https://cdn.nlark.com/yuque/0/2019/png/333810/1574243165093-102c6f18-c565-4e0f-a2dc-a374ccc412d4.png#align=left&amp;display=inline&amp;height=383&amp;name=image.png&amp;originHeight=766&amp;originWidth=1256&amp;search=&amp;size=414042&amp;status=done&amp;width=628" alt="image.png"></p>
<p>这样的设计比较好的定义了Pilot的职责，就是整个Service Mesh的控制面，但是不感知任何Istio以外的组件，即使是K8S也是如此。所有与外部组件包括注册中心和配置中心的交互逻辑，都移到了Pilot进程以外，通过运行特定的MCP Server来与Pilot进行通讯。Galley的职责，我认为是Pilot中默认的配置来源的MCP Server，目前是实现了与K8S数据的对接。这个文档中还定义了Pilot与Pilot之间的数据访问也是通过MCA（基于MCP协议定义的API），但是文档里没有提供更多的细节，会不会是Pilot未来会支持数据的分片以提高Pilot整体的数据容量？</p>
<p><a name="GiDba"></a></p>
<h1>协议定义</h1>
<p>看完了Pilot的整体演进架构，我们来看一下MCP协议的设计[2]，MCP协议在设计上参考了与Envoy的交互协议xDS。<br /><img src="https://cdn.nlark.com/yuque/0/2019/png/333810/1574243165174-59e66666-d992-440d-b066-89d1825abc38.png#align=left&amp;display=inline&amp;height=424&amp;name=image.png&amp;originHeight=594&amp;originWidth=944&amp;search=&amp;size=67856&amp;status=done&amp;width=674" alt="image.png"></p>
<p>在MCP协议中，定义了两个身份：Sink和Source。Sink指代的是数据的接收端，Source指代的是数据的发送端即数据源。MCP协议基于gRPC双向流协议进行定义，Sink端和Source端都可以随时往对端发送数据，相互不会阻塞。从上图的协议交互也可以看出，Sink端可以主动发送RequestResources请求来向Source端要求数据，同时Source端也可以主动将Resources数据发送给Sink端。Sink端在收到数据后会返回一个ACK确认。在RequestResources请求和ACK响应中，主要有两个字段：</p>
<ul>
<li>collection：表示此次请求需要的数据类型，目前Istio定义了17种类型（测试得出，实际数据以Istio官方说法为准），其中包含了serviceentries作为服务发现的数据等。</li>
<li>nonce：类似于请求的ID，用来与响应或者请求进行匹配。</li>
</ul>
<p>而在返回的数据中，还有一个字段就是resources字段，里面包含真正的数据，具体的数据格式和collection的类型有关。</p>
<p>同时MCP协议还定义了增量推送的能力，如下图所示。可以在RequestResouces请求中增加incremental=true字段，这样Sink在收到数据后，会根据增量的形式进行数据的更新。协议的文档中还指出，必须在RequestResouces请求中包含incremental=true的情况下，才能返回给Sink增量的数据，否则Sink端对于该数据的处理将是未知的。目前社区的Pilot还没有支持增量的MCP数据推送，从下一节的源码分析中可以看到，Pilot对于每一个Source（Pilot可以配置多个Source，每个Source之间的数据是隔离的）发送的数据，都是整体替换更新的。目前社区的一个进展是正在进行serviceentries类型数据的增量更新的支持，而且是endpoints粒度的增量更新[3]。</p>
<p><img src="https://cdn.nlark.com/yuque/0/2019/png/333810/1574243165196-05ba5a17-e84b-44cc-89e8-9e7ee00c9fa4.png#align=left&amp;display=inline&amp;height=403&amp;name=image.png&amp;originHeight=594&amp;originWidth=1068&amp;search=&amp;size=75600&amp;status=done&amp;width=724" alt="image.png"></p>
<p><a name="C3kOS"></a></p>
<h1>Pilot Sink端启动流程</h1>
<p>Pilot在启动的时候，会根据ConfigMap里的配置，进行MCP Server的初始化。主要的逻辑可以参考下图：</p>
<p><a name="rETVj"></a></p>
<h1><img src="https://cdn.nlark.com/yuque/0/2019/png/333810/1574243165184-426a4245-ef40-4c44-9bbe-d36326e3151a.png#align=left&amp;display=inline&amp;height=1151&amp;name=istio%20mcp.png&amp;originHeight=1151&amp;originWidth=951&amp;search=&amp;size=94058&amp;status=done&amp;width=951" alt="istio mcp.png"></h1>
<p>Pilot启动时，会调用server.NewServer来新建Pilot Server。在此过程中，会去读取ConfigSource配置里面的address。由于可能会配置多个address，那么Pilot在这里会循环去创建多个Sink客户端①，每一个Sink客户端拥有独立的数据。在这里有一点要注意的是，这个循环中会尝试与每个MCP Server建立gRPC连接，而如果其中一个MCP Server连接不上的话，整个循环就会推出，并返回error。也就是说如果Pilot在启动过程中无法连上每一个MCP Server，那么Pilot就会处于不健康状态，而在运行时没有这个限制②。当Sink客户端都新建完以后，就会再次循环异步调用每个Sink客户端的run方法，进行数据的收发了。</p>
<p>Sink端的run方法主要是调用EstablishResouceStream方法来建立双向流连接。在连接建立后，会调用creatIntialRquests请求来创建一次初始请求③，也就是说Pilot不会在启动时阻塞的去从每个MCP Server拉取数据，更新完后再提供服务，而是异步的进行数据的请求。事实上，Pilot也只会主动发这一次数据的请求④，接下来的数据更新都依赖于MCP Server的主动推送。在收到数据后，则进行handleResponse方法进行数据的更新⑤。</p>
<p><a name="dWz8x"></a></p>
<h1>Pilot Sink端处理流程</h1>
<p>下面介绍的是Pilot的Sink端在接收到数据的处理逻辑。从下图中可以看出，在接收到数据后，会先判断是否返回了错误，如果返回错误则直接结束数据的更新。如果没有错误，则进入Apply(change)方法。在这个方法中，会先新建一个innerStore的Map来保存更新到的数据。然后会将原来的configStore里对应collection类型的数据直接由这个innerStore进行替换。因此可以看出Pilot目前还不支持增量的MCP数据推送。在更新完数据后，则调用serviceEntryEvents或者ClearDiscoveryServerCache来通知Envoy等组件进行数据的更新。</p>
<p><img src="https://cdn.nlark.com/yuque/0/2019/png/333810/1574243165176-751ae4ee-eaab-4395-a4d1-4c2531b66d4c.png#align=left&amp;display=inline&amp;height=638&amp;name=istio%20mcp2.png&amp;originHeight=771&amp;originWidth=618&amp;search=&amp;size=52868&amp;status=done&amp;width=511" alt="istio mcp2.png"></p>
<p><a name="s5oWA"></a></p>
<h1>总结与展望</h1>
<p>目前Source端可以参考的代码有Galley，以及Nacos开发的独立MCP Server，用于进行MCP功能的测试和压测[4]，以及和Nacos Server一起部署的Java版本的MCP Server[5]。本文不做详细介绍，有兴趣的同学可以自行阅读相关源代码。</p>
<p>整体来看目前Pilot MCP协议还处于快速的更新和迭代阶段，未来可能还会有很多的变化。但是Istio基于MCP协议进行重构的大方向应该是不会跑了。Nacos团队目前也在密切关注着Istio及其他云原生组件的发展方向，同时将会陆续发布相关的功能，敬请期待。</p>
<p>[1] Pilot重构设计文档 <a href="https://docs.google.com/document/d/1S5ygkxR1alNI8cWGG4O4iV8zp8dA6Oc23zQCvFxr83U/edit#">https://docs.google.com/document/d/1S5ygkxR1alNI8cWGG4O4iV8zp8dA6Oc23zQCvFxr83U/edit#</a><br />[2] MCP协议介绍 <a href="https://github.com/istio/api/tree/master/mcp">https://github.com/istio/api/tree/master/mcp</a><br />[3] Pilot serviceentries增量推送的PR <a href="https://github.com/istio/istio/pull/12276">https://github.com/istio/istio/pull/12276</a><br />[4] Nacos提供的独立的MCP Server，Go语言开发 <a href="https://github.com/nacos-group/nacos-istio">https://github.com/nacos-group/nacos-istio</a><br />[5] Nacos对接Istio的issue，以及相关的commits <a href="https://github.com/alibaba/nacos/issues/1409">https://github.com/alibaba/nacos/issues/1409</a></p>
</section><footer class="footer-container"><div class="footer-body"><img src="/img/nacos_gray.png"/><div class="cols-container"><div class="col col-12"><h3>愿景</h3><p>Nacos 通过提供简单易用的动态服务发现、服务配置、服务共享与管理等服务基础设施，帮助用户在云原生时代，在私有云、混合云或者公有云等所有云环境中，更好的构建、交付、管理自己的微服务平台，更快的复用和组合业务服务，更快的交付商业创新的价值，从而为用户赢得市场。</p></div><div class="col col-6"><dl><dt>文档</dt><dd><a href="/zh-cn/docs/what-is-nacos.html" target="_self">概览</a></dd><dd><a href="/zh-cn/docs/quick-start.html" target="_self">快速开始</a></dd><dd><a href="/zh-cn/docs/contributing.html" target="_self">开发者指南</a></dd></dl></div><div class="col col-6"><dl><dt>资源</dt><dd><a href="/zh-cn/community/index.html" target="_self">社区</a></dd><dd><a href="https://www.aliyun.com/product/acm?source_type=nacos_pc_20181219" target="_self">云服务 ACM</a></dd><dd><a href="https://www.aliyun.com/product/edas?source_type=nacos_pc_20181219" target="_self">云服务 EDAS</a></dd><dd><a href="https://www.aliyun.com/product/ahas?source_type=nacos_pc_20190225" target="_self">云服务 AHAS</a></dd></dl></div></div><div class="copyright"><span>@ 2018 The Nacos Authors | An Alibaba Middleware (Aliware) Project</span></div></div></footer></div></div>
	<script src="https://f.alicdn.com/react/15.4.1/react-with-addons.min.js"></script>
	<script src="https://f.alicdn.com/react/15.4.1/react-dom.min.js"></script>
	<script>
		window.rootPath = '';
  </script>
	<script src="/build/blogDetail.js"></script>
</body>
</html>